package cn.zjxiliu.lib_config;

import android.content.Context;
import android.text.TextUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * Created by jessie on 2018/10/27.
 */

public class PropertiesConfigParser extends AbsConfigParser {

    @Override
    public <T> T useParser(Context context, T entity) {
        try {
            Properties properties = AssertsResUtils.getConfigProperties(context, entity.getClass().getSimpleName() + ".properties");
            Field[] fields = entity.getClass().getDeclaredFields();
            for (Field field : fields){
                field.setAccessible(true);
                String name = field.getName();
                String value = properties.getProperty(name);
                if(TextUtils.isEmpty(value)){
                    continue;
                }

                if(value.startsWith("{") && value.endsWith("}")){
                    parserBean(name, value, entity);
                }else if(value.startsWith("[") && value.endsWith("]")){
                    parserList(name, value, entity);
                }else{
                    setFieldValue(field, value, entity);
                }
            }
            return entity;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private <T> void parserList(String name, String value, T entity) {
        try {
            Field field = entity.getClass().getDeclaredField(name);
            field.setAccessible(true);
            ParameterizedType listGenericType = (ParameterizedType) field.getGenericType();
            Class<?> item = (Class<?>) listGenericType.getActualTypeArguments()[0];
            List<Object> itemList = new ArrayList();
            field.set(entity, itemList);
            JSONArray jsonArray = new JSONArray(value);
            for (int i = 0; i < jsonArray.length(); i ++){
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                Object itemObj = item.newInstance();
                itemList.add(itemObj);
                Field[] itemObjFields = itemObj.getClass().getDeclaredFields();
                for (Field itemObjF : itemObjFields){
                    itemObjF.setAccessible(true);
                    setJSONFieldValue(itemObjF, jsonObject, itemObj);
                }
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }


    }


    private void setFieldValue(Field field, String value, Object obj){
        String fieldType = field.getType().getName().toLowerCase();
        try {
            if(fieldType.contains("string")){
                field.set(obj, value);
            }else if(fieldType.contains("int")){
                field.setInt(obj, Integer.parseInt(value));
            }else if(fieldType.contains("boolean")){
                field.setBoolean(obj, Boolean.parseBoolean(value));
            }else if(fieldType.contains("double")){
                field.setDouble(obj, Double.parseDouble(value));
            }else if(fieldType.contains("long")){
                field.setLong(obj, Long.parseLong(value));
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }





    /**
     * 解析对象
     * @param name
     * @param value
     * @param entity
     * @param <T>
     */
    private <T> void parserBean(String name, String value, T entity) {
        try {
            Field field = entity.getClass().getDeclaredField(name);
            field.setAccessible(true);
            Object obj = Class.forName(field.getType().getName()).newInstance();
            field.set(entity, obj);
            Field[] itemFields = obj.getClass().getDeclaredFields();
            JSONObject jsonObject = new JSONObject(value);
            for (Field item : itemFields){
                item.setAccessible(true);
                setJSONFieldValue(item, jsonObject, obj);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    private void setJSONFieldValue(Field field, JSONObject jsonObject, Object obj){
        String fieldType = field.getType().getName().toLowerCase();
        try {
            if(fieldType.contains("string")){
                field.set(obj, jsonObject.optString(field.getName()));
            }else if(fieldType.contains("int")){
                field.setInt(obj, jsonObject.optInt(field.getName()));
            }else if(fieldType.contains("boolean")){
                field.setBoolean(obj, jsonObject.optBoolean(field.getName()));
            }else if(fieldType.contains("double")){
                field.setDouble(obj, jsonObject.optDouble(field.getName()));
            }else if(fieldType.contains("long")){
                field.setLong(obj, jsonObject.optLong(field.getName()));
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }





    @Override
    public ParserType getCurrentParserType() {
        return ParserType.TYPE_PROPERTIES;
    }
}
